use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json::json;
use serde_reflection::{ContainerFormat, Format, Samples, Tracer, TracerConfig, Value};

use super::my_err::MyErr;

/// 获取 Struct 的名称，字段，值。
/// 但是该方法在获取 包含其它 Struct 的 Struct 信息的时候出错
#[allow(dead_code)]
pub fn get_struct_info<T: Serialize + DeserializeOwned>(
    bean: &T,
) -> Result<(String, Vec<String>, Vec<Value>), MyErr> {
    let mut name = String::from("");
    let mut keys: Vec<String> = Vec::new();
    let mut values: Vec<Value> = Vec::new();

    let mut tracer = Tracer::new(TracerConfig::default());
    let mut samples = Samples::new();
    tracer
        .trace_simple_type::<T>()
        .map_err(|e| MyErr::System(e.to_string()))?;
    tracer
        .trace_simple_type::<rust_decimal::Decimal>()
        .map_err(|e| MyErr::System(e.to_string()))?;
    let (format, value) = tracer
        .trace_value(&mut samples, bean)
        .map_err(|e| MyErr::System(e.to_string()))?;
    //log::debug!("<<< {:?}", format);
    log::debug!(">>> {:?}", value);

    match format {
        Format::TypeName(s) => {
            name = s;
        }
        _ => (),
    }

    match value {
        Value::Seq(vlist) => {
            values.append(&mut vlist.clone());
        }
        _ => (),
    }

    // 获取字段名
    let registry = tracer
        .registry()
        .map_err(|e| MyErr::System(e.to_string()))?;
    if let Some(struct_type) = registry.get(&name) {
        match struct_type {
            ContainerFormat::Struct(vlist) => {
                for item in vlist {
                    keys.push(item.name.clone());
                }
            }
            _ => (),
        }
    }

    if !name.is_empty() && keys.len() > 0 && values.len() > 0 {
        Ok((name, keys, values))
    } else {
        Err(MyErr::Msg("获取 Struct 信息失败！".to_string()))
    }
}


/// 获取 结构体的名称，字段，值。
/// 注意：该函数未完全，暂无法获取结构体名称
pub fn get_struct_info_by_json<T: Serialize + DeserializeOwned>(
    bean: &T,
) -> Result<(String, Vec<String>, Vec<serde_json::Value>), MyErr> {
    let mut _name = String::from("");
    let mut keys: Vec<String> = Vec::new();
    let mut values: Vec<serde_json::Value> = Vec::new();

    let json_data = json!(bean);
    if let Some(json_obj) = json_data.as_object() {
        for k in json_obj.keys() {
            if let Some(v) = json_data.get(k) {
                keys.push(k.clone());
                values.push(v.clone());
            }
        }
    }

    if values.len() > 0 {
        Ok((_name, keys, values))
    } else {
        Err(MyErr::Msg("获取 Struct 信息失败！".to_string()))
    }
}
